library(dplyr)
library(sf)
library(tidyverse)
library(leaflet)
library(sf)
library(leaflet.providers)
library(RColorBrewer)
library(tigris)
Dot Density Plot
education_url <- "https://github.com/dyerlab/ENVS-Lectures/raw/master/data/edu_attainment-shp.zip"
file <- tempfile(pattern = "edu", tmpdir = ".", fileext = ".zip")
file
[1] ".\\edu253c7a4044d8.zip"
download.file(education_url, destfile = file)
trying URL 'https://github.com/dyerlab/ENVS-Lectures/raw/master/data/edu_attainment-shp.zip'
Content type 'application/zip' length 285435 bytes (278 KB)
downloaded 278 KB
unzip(file, exdir = ".")
points <- st_read("edu_attainment-shp")
Reading layer `edu_attainment' from data source `C:\Users\Charis\Documents\Spring2021\GISinR\GISinR\ENVS-Lectures\edu_attainment-shp' using driver `ESRI Shapefile'
Simple feature collection with 15745 features and 1 field
geometry type: POINT
dimension: XY
bbox: xmin: -77.59891 ymin: 37.44779 xmax: -77.38568 ymax: 37.60228
geographic CRS: WGS 84
Convert education levels to factor - this allows us to use colorFactor() to create our color palette
points$education <- factor(points$education, levels = c("No HS diploma", "HS, no Bachelors", "Bachelors" , "Post-Bachelors" ))
Create color palette
factpal <- colorFactor(brewer.pal(n = 4, name = "RdBu"), points$education) #used to color categorical data
Create dot density plot
leaflet(points) %>%
addProviderTiles(providers$CartoDB.Positron)%>% #add provider tiles
addCircles(stroke = FALSE, fillOpacity = 1, #add points
color = ~factpal(education)) %>% #color based on educational attainment
addLegend(pal = factpal, values = ~education, title = "Education Attainment")%>% #add legend
addScaleBar(position = "bottomright") #add scale bar
Choropleth plot
load in the census tract data
tracts <- tracts("VA", "Richmond city") %>%
st_transform(4326)
Using FIPS code '51' for state 'VA'
Using FIPS code '760' for 'Richmond city'
Data Prep
edu_tracts <- tracts %>%
st_buffer(dist = 0) %>% # buffer by 0 to avoid error message
st_intersection(points) # intersect the two data sets
edu_tracts %>%
group_by(NAME, education) %>% # group by tract name and education level
tally() -> tally # tally() counts the number of rows for the groups, so output is one row for every attainment level for each tract (so if a tract has all 4 attainment levels, there are 4 rows of data for that tract)
tally
Simple feature collection with 246 features and 3 fields
geometry type: GEOMETRY
dimension: XY
bbox: xmin: -77.59891 ymin: 37.44779 xmax: -77.38568 ymax: 37.60228
geographic CRS: WGS 84
tally <- as.data.frame(tally) # converted to data.frame to be able to drop the geometry because the `pivot_wider()` function would not work the way I wanted it to when the geometry was present
tally <- tally %>%
select(NAME, education, n)%>% # do not want the geometry
pivot_wider(names_from = education, values_from = n) # pivot the table so that instead of having multiple rows per tract, you have one row per tract with a column for each attainment level
tally[is.na(tally)] <- 0 # define NA values as zero
Create attainment metric for choropleth
tally <- tally %>%
mutate(edu = (((`No HS diploma` * 1) + (`HS, no Bachelors` * 2) + (`Bachelors` * 3) + (`Post-Bachelors` * 4))/
(`No HS diploma` + `HS, no Bachelors` + `Bachelors` + `Post-Bachelors`)))
# I created a column, edu, and did a weighted average for each row. So 'No HS diploma' was weighted as 1, 'HS, no Bachelors' as 2, ect.
# I used this new column as my average education attainment value to color my polygons
tally %>%
select(NAME, edu) -> tally # no longer need the individual count data
Join the education data back with the tract data
tracts %>%
left_join(tally, by = "NAME") -> tracts
Create the palette
pal <- colorNumeric(
palette = "RdBu",
domain = tracts$edu) # This time I want a continuos palatte, so I used `colorNumeric()`
Make the choropleth map
leaflet(tracts) %>%
addProviderTiles(providers$CartoDB.Positron)%>% # add provider tiles
addPolygons( fillOpacity = 1, # add tract polygons
fillColor = ~pal(edu), smoothFactor = 0.2, # fill color based on the calculated 'edu' metric
color = "grey",
opacity = 1,
weight = 1) %>%
addLegend(pal = pal, values = ~edu, title = "Education Attainment") # add legend
I did not like this legend, as it’s unclear what the numbers mean. With some googling I found a solution
labels <-c("No HS diploma (1)", "HS, no Bachelors (2)",
"Bachelors (3)" , "Post-Bachelors (4)" ) # define the labels for the legend
leaflet(tracts) %>%
addProviderTiles(providers$CartoDB.Positron)%>% # add provider tiles
addPolygons( fillOpacity = 1, # add tract polygons
fillColor = ~pal(edu), smoothFactor = 0.2, # fill color based on the calculated 'edu' metric
color = "grey",
opacity = 1,
weight = 1) %>%
addLegend(pal = pal, values = ~edu,
opacity = 1,
title = "Education Attainment",
labFormat = function(type, cuts, p) { # Here's the trick
paste0(labels)
})
That looks better, I think
Combine the maps
Final map
LS0tDQp0aXRsZTogIkxlYWZsZXQgSG9tZXdvcmsgS2V5Ig0KYXV0aG9yOiAiQ2hhcmlzIERlYWR3eWxlciINCmRhdGU6ICIzLzE1LzIwMjEiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGxlYWZsZXQpDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShsZWFmbGV0LnByb3ZpZGVycykNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KbGlicmFyeSh0aWdyaXMpDQpgYGANCg0KIyMjIERvdCBEZW5zaXR5IFBsb3QNCmBgYHtyfQ0KZWR1Y2F0aW9uX3VybCA8LSAiaHR0cHM6Ly9naXRodWIuY29tL2R5ZXJsYWIvRU5WUy1MZWN0dXJlcy9yYXcvbWFzdGVyL2RhdGEvZWR1X2F0dGFpbm1lbnQtc2hwLnppcCINCg0KZmlsZSA8LSB0ZW1wZmlsZShwYXR0ZXJuID0gImVkdSIsIHRtcGRpciA9ICIuIiwgZmlsZWV4dCA9ICIuemlwIikNCmZpbGUNCg0KZG93bmxvYWQuZmlsZShlZHVjYXRpb25fdXJsLCBkZXN0ZmlsZSA9IGZpbGUpDQp1bnppcChmaWxlLCBleGRpciA9ICIuIikNCg0KDQpwb2ludHMgPC0gc3RfcmVhZCgiZWR1X2F0dGFpbm1lbnQtc2hwIikNCmBgYA0KDQpDb252ZXJ0IGVkdWNhdGlvbiBsZXZlbHMgdG8gZmFjdG9yIC0gdGhpcyBhbGxvd3MgdXMgdG8gdXNlIGBjb2xvckZhY3RvcigpYCB0byBjcmVhdGUgb3VyIGNvbG9yIHBhbGV0dGUNCmBgYHtyfQ0KcG9pbnRzJGVkdWNhdGlvbiA8LSBmYWN0b3IocG9pbnRzJGVkdWNhdGlvbiwgbGV2ZWxzID0gYygiTm8gSFMgZGlwbG9tYSIsICJIUywgbm8gQmFjaGVsb3JzIiwgIkJhY2hlbG9ycyIgLCAiUG9zdC1CYWNoZWxvcnMiICApKSANCmBgYA0KDQpDcmVhdGUgY29sb3IgcGFsZXR0ZQ0KYGBge3J9DQpmYWN0cGFsIDwtIGNvbG9yRmFjdG9yKGJyZXdlci5wYWwobiA9IDQsIG5hbWUgPSAiUmRCdSIpLCBwb2ludHMkZWR1Y2F0aW9uKSAjdXNlZCB0byBjb2xvciBjYXRlZ29yaWNhbCBkYXRhDQpgYGANCg0KDQpDcmVhdGUgZG90IGRlbnNpdHkgcGxvdA0KYGBge3J9DQpsZWFmbGV0KHBvaW50cykgJT4lIA0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLlBvc2l0cm9uKSU+JSAjYWRkIHByb3ZpZGVyIHRpbGVzDQogIGFkZENpcmNsZXMoc3Ryb2tlID0gRkFMU0UsICBmaWxsT3BhY2l0eSA9IDEsICNhZGQgcG9pbnRzDQogICAgICAgICAgICAgIGNvbG9yID0gfmZhY3RwYWwoZWR1Y2F0aW9uKSkgJT4lICNjb2xvciBiYXNlZCBvbiBlZHVjYXRpb25hbCBhdHRhaW5tZW50DQogIGFkZExlZ2VuZChwYWwgPSBmYWN0cGFsLCB2YWx1ZXMgPSB+ZWR1Y2F0aW9uLCB0aXRsZSA9ICJFZHVjYXRpb24gQXR0YWlubWVudCIpJT4lICNhZGQgbGVnZW5kDQogIGFkZFNjYWxlQmFyKHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0IikgI2FkZCBzY2FsZSBiYXINCmBgYA0KDQojIyMgQ2hvcm9wbGV0aCBwbG90DQoNCmxvYWQgaW4gdGhlIGNlbnN1cyB0cmFjdCBkYXRhDQpgYGB7cn0NCnRyYWN0cyA8LSB0cmFjdHMoIlZBIiwgIlJpY2htb25kIGNpdHkiKSAlPiUNCiAgc3RfdHJhbnNmb3JtKDQzMjYpDQpgYGANCg0KRGF0YSBQcmVwDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KZWR1X3RyYWN0cyA8LSB0cmFjdHMgJT4lDQogIHN0X2J1ZmZlcihkaXN0ID0gMCkgJT4lICMgYnVmZmVyIGJ5IDAgdG8gYXZvaWQgZXJyb3IgbWVzc2FnZQ0KICBzdF9pbnRlcnNlY3Rpb24ocG9pbnRzKSAjIGludGVyc2VjdCB0aGUgdHdvIGRhdGEgc2V0cw0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQplZHVfdHJhY3RzICU+JQ0KICBncm91cF9ieShOQU1FLCBlZHVjYXRpb24pICU+JSAjIGdyb3VwIGJ5IHRyYWN0IG5hbWUgYW5kIGVkdWNhdGlvbiBsZXZlbA0KICB0YWxseSgpIC0+IHRhbGx5ICMgdGFsbHkoKSBjb3VudHMgdGhlIG51bWJlciBvZiByb3dzIGZvciB0aGUgZ3JvdXBzLCBzbyBvdXRwdXQgaXMgb25lIHJvdyBmb3IgZXZlcnkgYXR0YWlubWVudCBsZXZlbCBmb3IgZWFjaCB0cmFjdCAoc28gaWYgYSB0cmFjdCBoYXMgYWxsIDQgYXR0YWlubWVudCBsZXZlbHMsIHRoZXJlIGFyZSA0IHJvd3Mgb2YgZGF0YSBmb3IgdGhhdCB0cmFjdCkNCg0KdGFsbHkNCmBgYA0KDQpgYGB7cn0NCnRhbGx5IDwtIGFzLmRhdGEuZnJhbWUodGFsbHkpICMgY29udmVydGVkIHRvIGRhdGEuZnJhbWUgdG8gYmUgYWJsZSB0byBkcm9wIHRoZSBnZW9tZXRyeSBiZWNhdXNlIHRoZSBgcGl2b3Rfd2lkZXIoKWAgZnVuY3Rpb24gd291bGQgbm90IHdvcmsgdGhlIHdheSBJIHdhbnRlZCBpdCB0byB3aGVuIHRoZSBnZW9tZXRyeSB3YXMgcHJlc2VudA0KDQp0YWxseSA8LSB0YWxseSAlPiUNCiAgc2VsZWN0KE5BTUUsIGVkdWNhdGlvbiwgbiklPiUgIyBkbyBub3Qgd2FudCB0aGUgZ2VvbWV0cnkgDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBlZHVjYXRpb24sIHZhbHVlc19mcm9tID0gbikgIyBwaXZvdCB0aGUgdGFibGUgc28gdGhhdCBpbnN0ZWFkIG9mIGhhdmluZyBtdWx0aXBsZSByb3dzIHBlciB0cmFjdCwgeW91IGhhdmUgb25lIHJvdyBwZXIgdHJhY3Qgd2l0aCBhIGNvbHVtbiBmb3IgZWFjaCBhdHRhaW5tZW50IGxldmVsDQoNCnRhbGx5W2lzLm5hKHRhbGx5KV0gPC0gMCAjIGRlZmluZSBOQSB2YWx1ZXMgYXMgemVybw0KYGBgDQoNCkNyZWF0ZSBhdHRhaW5tZW50IG1ldHJpYyBmb3IgY2hvcm9wbGV0aA0KDQpgYGB7cn0NCnRhbGx5IDwtIHRhbGx5ICU+JQ0KICBtdXRhdGUoZWR1ID0gKCgoYE5vIEhTIGRpcGxvbWFgICogMSkgKyAoYEhTLCBubyBCYWNoZWxvcnNgICogMikgKyAoYEJhY2hlbG9yc2AgKiAzKSArIChgUG9zdC1CYWNoZWxvcnNgICogNCkpLw0KICAgICAgICAgICAgICAgICAgKGBObyBIUyBkaXBsb21hYCAgKyBgSFMsIG5vIEJhY2hlbG9yc2AgKyBgQmFjaGVsb3JzYCArIGBQb3N0LUJhY2hlbG9yc2ApKSkNCg0KIyBJIGNyZWF0ZWQgYSBjb2x1bW4sIGVkdSwgYW5kIGRpZCBhIHdlaWdodGVkIGF2ZXJhZ2UgZm9yIGVhY2ggcm93LiBTbyAnTm8gSFMgZGlwbG9tYScgd2FzIHdlaWdodGVkIGFzIDEsICdIUywgbm8gQmFjaGVsb3JzJyBhcyAyLCBlY3QuIA0KDQojIEkgdXNlZCB0aGlzIG5ldyBjb2x1bW4gYXMgbXkgYXZlcmFnZSBlZHVjYXRpb24gYXR0YWlubWVudCB2YWx1ZSB0byBjb2xvciBteSBwb2x5Z29ucw0KYGBgDQoNCmBgYHtyfQ0KdGFsbHkgJT4lDQogIHNlbGVjdChOQU1FLCBlZHUpIC0+IHRhbGx5ICMgbm8gbG9uZ2VyIG5lZWQgdGhlIGluZGl2aWR1YWwgY291bnQgZGF0YQ0KYGBgDQoNCkpvaW4gdGhlIGVkdWNhdGlvbiBkYXRhIGJhY2sgd2l0aCB0aGUgdHJhY3QgZGF0YQ0KDQpgYGB7cn0NCnRyYWN0cyAlPiUNCiAgbGVmdF9qb2luKHRhbGx5LCBieSA9ICJOQU1FIikgLT4gdHJhY3RzDQpgYGANCg0KQ3JlYXRlIHRoZSBwYWxldHRlDQoNCmBgYHtyfQ0KcGFsIDwtIGNvbG9yTnVtZXJpYygNCiAgcGFsZXR0ZSA9ICJSZEJ1IiwNCiAgZG9tYWluID0gdHJhY3RzJGVkdSkgIyBUaGlzIHRpbWUgSSB3YW50IGEgY29udGludW9zIHBhbGF0dGUsIHNvIEkgdXNlZCBgY29sb3JOdW1lcmljKClgDQpgYGANCg0KTWFrZSB0aGUgY2hvcm9wbGV0aCBtYXANCg0KYGBge3J9DQpsZWFmbGV0KHRyYWN0cykgJT4lDQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24pJT4lICMgYWRkIHByb3ZpZGVyIHRpbGVzDQogIGFkZFBvbHlnb25zKCBmaWxsT3BhY2l0eSA9IDEsICMgYWRkIHRyYWN0IHBvbHlnb25zDQogICAgICAgICAgICAgICBmaWxsQ29sb3IgPSB+cGFsKGVkdSksIHNtb290aEZhY3RvciA9IDAuMiwgIyBmaWxsIGNvbG9yIGJhc2VkIG9uIHRoZSBjYWxjdWxhdGVkICdlZHUnIG1ldHJpYw0KICAgICAgICAgICAgICAgY29sb3IgPSAiZ3JleSIsIA0KICAgICAgICAgICAgICAgb3BhY2l0eSA9IDEsDQogICAgICAgICAgICAgICB3ZWlnaHQgPSAxKSAlPiUNCiAgYWRkTGVnZW5kKHBhbCA9IHBhbCwgdmFsdWVzID0gfmVkdSwgdGl0bGUgPSAiRWR1Y2F0aW9uIEF0dGFpbm1lbnQiKSAjIGFkZCBsZWdlbmQNCmBgYA0KDQpJIGRpZCBub3QgbGlrZSB0aGlzIGxlZ2VuZCwgYXMgaXQncyB1bmNsZWFyIHdoYXQgdGhlIG51bWJlcnMgbWVhbi4gV2l0aCBzb21lIGdvb2dsaW5nIEkgZm91bmQgYSBzb2x1dGlvbg0KDQpgYGB7cn0NCmxhYmVscyA8LWMoIk5vIEhTIGRpcGxvbWEgKDEpIiwgIkhTLCBubyBCYWNoZWxvcnMgKDIpIiwNCiAgICAgICAgICAgIkJhY2hlbG9ycyAoMykiICwgIlBvc3QtQmFjaGVsb3JzICg0KSIgICkgIyBkZWZpbmUgdGhlIGxhYmVscyBmb3IgdGhlIGxlZ2VuZA0KYGBgDQoNCmBgYHtyfQ0KbGVhZmxldCh0cmFjdHMpICU+JQ0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLlBvc2l0cm9uKSU+JSAjIGFkZCBwcm92aWRlciB0aWxlcw0KICBhZGRQb2x5Z29ucyggZmlsbE9wYWNpdHkgPSAxLCAjIGFkZCB0cmFjdCBwb2x5Z29ucw0KICAgICAgICAgICAgICAgZmlsbENvbG9yID0gfnBhbChlZHUpLCBzbW9vdGhGYWN0b3IgPSAwLjIsICMgZmlsbCBjb2xvciBiYXNlZCBvbiB0aGUgY2FsY3VsYXRlZCAnZWR1JyBtZXRyaWMNCiAgICAgICAgICAgICAgIGNvbG9yID0gImdyZXkiLCANCiAgICAgICAgICAgICAgIG9wYWNpdHkgPSAxLA0KICAgICAgICAgICAgICAgd2VpZ2h0ID0gMSkgJT4lDQogIGFkZExlZ2VuZChwYWwgPSBwYWwsIHZhbHVlcyA9IH5lZHUsIA0KICAgICAgICAgICAgb3BhY2l0eSA9IDEsDQogICAgICAgICAgICB0aXRsZSA9ICJFZHVjYXRpb24gQXR0YWlubWVudCIsDQogICAgICAgICAgICBsYWJGb3JtYXQgPSBmdW5jdGlvbih0eXBlLCBjdXRzLCBwKSB7ICAjIEhlcmUncyB0aGUgdHJpY2sNCiAgICAgICAgICAgICAgcGFzdGUwKGxhYmVscykNCiAgICAgICAgICAgIH0pDQpgYGANClRoYXQgbG9va3MgYmV0dGVyLCBJIHRoaW5rDQoNCiMjIyBDb21iaW5lIHRoZSBtYXBzDQoNCmBgYHtyfQ0KDQpsZWFmbGV0KCkgJT4lICMgSSBkZWNpZGVkIHRvIGRlZmluZSBieSBkYXRhIGJ5IGxheWVyIGJlY2F1c2UgSSBoYXZlIG11bHRpcGxlIGRhdGEgc2V0cw0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLlBvc2l0cm9uKSAlPiUgIyBBZGQgcHJvdmlkZXIgdGlsZXMNCiAgYWRkUG9seWdvbnMoZGF0YSA9IHRyYWN0cywgIyBJIGRlY2lkZWQgdG8gcGxvdCB0aGUgdHJhY3RzIG9uIHRoZSBkb3QgZGVuc2l0eSBtYXANCiAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLA0KICAgICAgICAgICAgICB3ZWlnaHQgPSAxLA0KICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDAsDQogICAgICAgICAgICAgIGdyb3VwID0gIkNpcmNsZSIgIyBOZWVkIHRvIGdyb3VwcywgMSBmb3IgZGVuc2l0eSBwbG90IGFuZCAxIGZvciBjaG9yb3BsZXRoDQogICAgICAgICAgICAgICkgICU+JQ0KICBhZGRDaXJjbGVzKGRhdGEgPSBwb2ludHMsDQogICAgICAgICAgICAgc3Ryb2tlID0gRkFMU0UsICBmaWxsT3BhY2l0eSA9IDEsICNwbG90IHRoZSBjaXJjbGVzIG9uIHRvcCBvZiB0aGUgdHJhY3RzDQogICAgICAgICAgICAgY29sb3IgPSB+ZmFjdHBhbChlZHVjYXRpb24pLA0KICAgICAgICAgICAgIGdyb3VwID0gIkNpcmNsZSIgIyBEZWZpbmUgZ3JvdXANCiAgICAgICAgICAgICApICU+JQ0KICBhZGRMZWdlbmQoZGF0YSA9IHBvaW50cywNCiAgICAgICAgICAgIHBhbCA9IGZhY3RwYWwsICMgQWRkIGxlZ2VuZCBmb3IgZG90IGRlbnNpdHkgcGxvdA0KICAgICAgICAgICAgdmFsdWVzID0gfmVkdWNhdGlvbiwNCiAgICAgICAgICAgIG9wYWNpdHkgPSAxLA0KICAgICAgICAgICAgdGl0bGUgPSAiRWR1Y2F0aW9uYWwgQXR0YWlubWVudCIsDQogICAgICAgICAgICBncm91cCA9ICJDaXJjbGUiICMgRGVmaW5lIGdyb3VwIGZvciBsZWdlbmQNCiAgICAgICAgICAgICkgJT4lDQogIGdyb3VwT3B0aW9ucygiQ2lyY2xlIiwgem9vbUxldmVscyA9IDE6MTIgIyBEZWZpbmUgdGhlIHpvb20gbGV2ZWxzIGZvciB0aGUgZG90IGRlbnNpdHkgcGxvdCAoZG90cyB3aWxsIG9ubHkgYnkgdmlzaWJsZSBiZXR3ZWVuIHpvb20gbGV2ZWxzIDEgYW5kIDEyKQ0KICAgICAgICAgICAgICAgKSAlPiUNCiAgYWRkUG9seWdvbnMoIGRhdGEgPSB0cmFjdHMsICMgRmlyc3QgbGF5ZXIgb2YgdGhlIGNob3JvcGxldGggbWFwLCB0cmFjdCBwb2x5Z29ucw0KICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAuNzUsDQogICAgICAgICAgICAgICBmaWxsQ29sb3IgPSB+cGFsKGVkdSksIHNtb290aEZhY3RvciA9IDAuMiwgIyBDb2xvciBkZWZpbmVkIGJ5IGF0dGFpbm1lbnQgbWV0cmljDQogICAgICAgICAgICAgICBjb2xvciA9ICJncmV5IiwNCiAgICAgICAgICAgICAgIG9wYWNpdHkgPSAxLA0KICAgICAgICAgICAgICAgd2VpZ2h0ID0gMSwNCiAgICAgICAgICAgICAgIGdyb3VwID0gIkNob3JvIiAjIENhbGxlZCBteSBzZWNvbmQgZ3JvdXAgIkNob3JvIg0KICAgICAgICAgICAgICAgKSAlPiUNCiAgYWRkTGVnZW5kKGRhdGEgPSB0cmFjdHMsDQogICAgICAgICAgICBwYWwgPSBwYWwsICMgQWRkIGxlZ2VuZCBmb3IgY2hvcm9wbGV0aCBwbG90DQogICAgICAgICAgICB2YWx1ZXMgPSB+ZWR1LA0KICAgICAgICAgICAgb3BhY2l0eSA9IC43NSwNCiAgICAgICAgICAgIHRpdGxlID0gIkVkdWNhdGlvbmFsIEF0dGFpbm1lbnQiLA0KICAgICAgICAgICAgbGFiRm9ybWF0ID0gZnVuY3Rpb24odHlwZSwgY3V0cywgcCkgeyAgIyBIZXJlJ3MgdGhlIHRyaWNrIGFnYWluDQogICAgICAgICAgICAgIHBhc3RlMChsYWJlbHMpDQogICAgICAgICAgICB9LA0KICAgICAgICAgICAgZ3JvdXAgPSAiQ2hvcm8iICMgQWRkIHRvIGNob3JvcGxldGggZ3JvdXANCiAgICAgICAgICAgICkgJT4lDQogZ3JvdXBPcHRpb25zKCJDaG9ybyIsIHpvb21MZXZlbHMgPSAxMzoyMCAgIyBEZWZpbmUgbGV2ZWxzIGZvciB0aGUgY2hvcm9wbGV0aCBtYXAgKGNob3JvcGxldGggcG9seWdvbnMgd2lsbCBvbmx5IGJlIHZpc2JsZSBiZXR3ZWVuIHpvb20gbGV2bHMgMTMgYW5kIDIwKQ0KICAgICAgICAgICAgICApICU+JQ0KICBhZGRTY2FsZUJhcihwb3NpdGlvbiA9ICJib3R0b21yaWdodCIpICMgQWRkIHNjYWxlIGJhci4gU2NhbGUgYmFyIGRvZXMgbm90IG5lZWQgYSBncm91cCBiZWNhdXNlIEkgd2FudCBpdCB2aXNpYmxlIGF0IGFsbCB6b29tIGxldmVscw0KIA0KDQoNCmBgYA0KDQpGaW5hbCBtYXANCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=